﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;
using WordsHelper.DAL.Models.Data;
using WordsHelper.DAL.Services;
using WordsHelper.Model.Data;
using Timer = System.Windows.Forms.Timer;
using WordsHelper.DAL.Services.Data;

namespace WordsHelper
{
    public partial class FrmMain : Form
    {
        public FrmMain()
        {
            InitializeComponent();

            Frequency = new Random().Next(2, 11);

            dgvHistory.RowsDefaultCellStyle.Font = new Font("宋体", 12, FontStyle.Regular);
            Task.Factory.StartNew(delegate
                {
                    try
                    {
                        data = new DALDataTable(null);
                        data.SaveToCache();
                    }
                    catch
                    {
                        DALService.MoveDataFromBak();
                    }

                    BeginInvoke(new Action(delegate
                        {
                            Databind(data.Lists.Where(w => w.Important < Frequency).ToList());
                            tstbName.Focus();
                        }));
                });
            timer.Interval = REFRESH_INTERVAL;
            timer.Tick += delegate
                {
                    Task.Factory.StartNew(Save);
                };
            timer.Start();

            tstbMeaning.KeyUp += (sender, args) =>
                {
                    tstbName.BackColor = SystemColors.Window;
                    if (args.KeyCode != Keys.Enter)
                    {
                        return;
                    }

                    var name = tstbName.Text.Trim();
                    var meaning = tstbMeaning.Text.Trim();
                    if (name == string.Empty
                        || meaning == string.Empty
                        || data.Lists.Any(w => w.Name == name))
                    {
                        return;
                    }

                    data.Lists.Insert(0, new ModelDataTable { Name = name, Meaning = meaning, Important = 1 });
                    Databind(data.Lists.Where(w => w.Important < Frequency).ToList());
                    tstbName.Clear();
                    tstbMeaning.Clear();
                    tstbName.Focus();
                };
            tstbName.KeyUp += async (sender, args) =>
                {
                    tstbName.BackColor = SystemColors.Window;
                    var key = tstbName.Text.Trim();
                    if (key == string.Empty)
                    {
                        Databind(data.Lists.Where(w => w.Important < Frequency).ToList());
                        return;
                    }

                    if (args.KeyCode == Keys.Home)
                    {
                        tstbName.Clear();
                        Databind(data.Lists.Where(w => w.Important < Frequency).ToList());
                        return;
                    }

                    if (args.KeyCode == Keys.Enter)
                    {
                        if (data.Lists.Any(w => w.Name == key))
                        {
                            data.Lists.First(w => w.Name == key).Important++;
                            tstbName.Clear();
                            Databind(data.Lists.Where(w => w.Important < Frequency).ToList());
                            return;
                        }

                        string allString;
                        try
                        {
                            allString = await client.DownloadStringTaskAsync(GetUrl(key));
                        }
                        catch (Exception)
                        {
                            tstbName.BackColor = Color.Red;
                            return;
                        }

                        var groups = regex.Matches(allString);
                        if (groups.Count <= 0)
                        {
                            return;
                        }

                        result.Clear();
                        var headLength = "<span class=\"definition\">".Length;
                        var tailLength = "</span>".Length;
                        for (var i = 0; i < groups.Count; i++)
                        {
                            result.Add(new Word(i + 1, new string(groups[i].Value.Skip(headLength).Take(groups[i].Value.Length - headLength - tailLength).ToArray()).Trim().Trim('.').Trim(':').Replace("鈥檚", "'s").Replace("鈥榖", "‘b").Replace("鈥?", "’,")));
                        }

                        dgvDictionary.DataSource = null;
                        dgvDictionary.DataSource = result;
                        dgvDictionary.Columns[0].Width = 40;
                        dgvDictionary.Columns[1].Width = 540;
                        tstbName.Focus();
                        return;
                    }

                    Databind(data.Lists.Where(w => w.Name.StartsWith(key)).ToList());
                };
            tstbName.Leave += delegate
                {
                    tstbName.BackColor = SystemColors.Window;
                    Databind(data.Lists.Where(w => w.Important < Frequency).ToList());
                };
            tstbName.Click += delegate
                {
                    tstbName.BackColor = SystemColors.Window;
                    tstbName.Focus();
                };
            Closing += delegate
                {
                    Save();
                    DALService.CopyDataToBak();
                };
            tsbAdd.Click += delegate
                {
                    if (result.Count == 0)
                    {
                        return;
                    }

                    var index = dgvDictionary.SelectedRows[0].Index;
                    tstbMeaning.Text = result[index].Meaning;
                    tstbMeaning.Focus();
                    tstbMeaning.SelectionLength = 0;
                };
        }

        private void Save()
        {
            if (data.Lists == null || data.Lists.Count == 0)
            {
                return;
            }

            data.SaveChanges();
            data.SaveToCache();
            if (InvokeRequired)
            {
                BeginInvoke(new Action(delegate
                    {
                        Text = "自动保存于：" + DateTimeOffset.Now.ToString();
                    }));
            }
            else
            {
                Text = "自动保存于：" + DateTimeOffset.Now;
            }
        }

        private void Databind(IReadOnlyCollection<ModelDataTable> source)
        {
            dgvHistory.DataSource = null;
            if (source != null && source.Count == 0)
            {
                return;
            }

            dgvHistory.DataSource = source.Count <= SHOW_COUNT
                                           ? source.OrderByDescending(s => s.Important).ToList()
                                           : source.OrderByDescending(s => s.Important).Take(SHOW_COUNT).ToList();
            dgvHistory.Columns[0].Visible = false;
            dgvHistory.Columns[1].HeaderText = "名称";
            dgvHistory.Columns[1].Width = 145;
            dgvHistory.Columns[1].ReadOnly = true;
            dgvHistory.Columns[2].HeaderText = "含义";
            dgvHistory.Columns[2].Width = 375;
            dgvHistory.Columns[2].ReadOnly = true;
            dgvHistory.Columns[3].HeaderText = "重复";
            dgvHistory.Columns[3].Width = 40;
        }

        private static string GetUrl(string word)
        {
            var tmp = word;
            if (word.Contains('-'))
            {
                tmp = word.Replace("-", "--");
            }

            if (word.Contains(' '))
            {
                tmp = tmp.Replace(" ", "-");
                word = word.Replace(" ", "+");
            }

            return string.Format("http://oxforddictionaries.com/definition/english/{0}?q={1}", tmp, word);
        }

        private readonly Timer timer = new Timer();
        private DALDataTable data;
        private const int SHOW_COUNT = 25;
        private const int REFRESH_INTERVAL = 30000;
        private static int Frequency;
        private readonly WebClient client = new WebClient();
        private readonly Regex regex = new Regex("<span class=\"definition\">[^<]+</span>");
        private readonly List<Word> result = new List<Word>();
    }
}
